package com.cnbot.xfsixmicserialport.api;

import android.util.Log;

import com.nudt.serialport.utils.SerialPort;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.security.InvalidParameterException;

/**
 * Copyright (c) 2016--2019/2/22  Hunan Cnbot Co., Ltd. All Rights Reserved.
 *
 * @descriptoin 六麦唤醒事件
 * @FileName: WakeUpTools.java
 * @author: dc
 * @date: 2019/2/22 15:00
 * @version: 1.0
 */

public class WakeUpTools {
    /**
     * 数据最小长度
     */
    public static final int DATA_MIN_LEN = 6;
    private static WakeUpTools instance = null;
    private final String TAG = WakeUpTools.class.getSimpleName();
    /**
     * 串口读取数据
     **/
    protected OutputStream mMicOutputStream;
    /**
     * 六麦串口对象
     */
    private SerialPort mSerialPort = null;
    private InputStream mMicInputStream;
    private MicReadThread micReadThread;
    /**
     * 唤醒回调事件
     */
    private IWakeUpListener iWakeUpListener;
    /**
     * 串口解析
     **/
    private byte[] micByte = new byte[1024 * 10];
    /**
     * 数组下标
     */
    private int temp = 0;
    /**
     * 没有处理完数据的长度
     */
    private int unDisposeLen = 0;
    /**
     * 串口是否打开成功
     */
    private boolean isInit = false;

    public static WakeUpTools getInstance() {
        if (instance == null) {
            synchronized (WakeUpTools.class) {
                if (instance == null) {
                    instance = new WakeUpTools();
                }
            }
        }
        return instance;
    }

    /**
     * 打开串口
     *
     * @param baudrate 波特率
     * @param path     设备路径
     * @return 是否打开
     */
    public boolean openWakeSerialPort(int baudrate, String path) {
        try {
            Log.e(TAG, "打开串口");
            getSerialPort(baudrate, path);
            setInit(true);
        } catch (Exception e) {
            setInit(false);
        }
        return isInit();
    }

    /**
     * 获取是否打开串口状态
     *
     * @return
     */
    public boolean isInit() {
        return isInit;
    }

    /**
     * 设置打开串口状态
     *
     * @param init
     */
    public void setInit(boolean init) {
        isInit = init;
    }

    public void getSerialPort(int baudrate, String path) throws SecurityException, IOException, InvalidParameterException {
        Log.e(TAG, "path=" + path + "     baudrate=" + baudrate);
        //打开的是五麦
        if (mSerialPort == null) {
            /* Check parameters */
            if ((path.length() == 0) || (baudrate == -1)) {
                throw new InvalidParameterException();
            }
            mSerialPort = new SerialPort(new File(path), baudrate, 0);
            mMicOutputStream = mSerialPort.getOutputStream();
            mMicInputStream = mSerialPort.getInputStream();

        }
    }

    /**
     * 注册唤醒事件监听器
     *
     * @param iWakeUpListener
     */
    public void setiWakeUpListener(IWakeUpListener iWakeUpListener) {
        this.iWakeUpListener = iWakeUpListener;
    }

    /**
     * 注销监听器
     */
    public void removeiWakeUpListener() {
        this.iWakeUpListener = null;
    }


    /**
     * 启动唤醒
     */
    public void startWakeUp() {
        /* Create a receiving thread */
        micReadThread = new MicReadThread();
        micReadThread.start();
    }


    /**
     * 关闭唤醒
     */
    public void stopWakeUp() {
        if (micReadThread != null) {
            micReadThread.interrupt();
            micReadThread = null;
        }
    }


    /**
     * 六麦结果
     *
     * @throws IOException
     */
    private void micResult() throws IOException {
        byte[] buffer = new byte[512];
        int size;
        size = mMicInputStream.read(buffer);
        //获取串口传过来的数据：机器人状态信息数据
        if (size > 0 && unDisposeLen >= 0) {
            //获取串口传过来的数据
            System.arraycopy(buffer, 0, micByte, unDisposeLen, size);
            unDisposeLen += +size;
            //数组下标
            int temp = 0;
            while (temp <= unDisposeLen) {
                //判断数据长度是否足够：
                if (unDisposeLen - temp >= DATA_MIN_LEN) {
                    if (temp > 4 && micByte[temp] == 0x0a) {
                        /**  五麦数据解析   **/
                        byte[] by = new byte[temp];
                        System.arraycopy(micByte, 0, by, 0, temp);

                        String angleContent = byteToString(by, "utf-8").trim();
                        String[] info = angleContent.split("\n");
                        if (info != null && info.length > 0) {
                            String angle = info[info.length - 1];
                            Log.e(TAG, "content=" + angle);
                            if (angle.contains("angle:")) {
                                String angleValue = angle.split(" ")[1];
                                String[] an = angleValue.split(":");
                                String v = an[1];
                                Log.e(TAG, "angle = " + v);
                                if (iWakeUpListener != null) {
                                    iWakeUpListener.onWakeUp(v);
                                }
                            }
                        }

                        byte[] ret;
                        if (unDisposeLen - temp <= 0) {
                            //表示为一条完整数据，没有没处理完的数据，这里直接清空b数组
                            ret = new byte[unDisposeLen];
                        } else {
                            ret = new byte[unDisposeLen - temp];
                        }
                        //将处理的数据copy到ret数组中
                        System.arraycopy(micByte, temp, ret, 0, ret.length);
                        //将未处理的数据ret替换从0开始替换到
                        System.arraycopy(ret, 0, micByte, 0, ret.length);
                        unDisposeLen = unDisposeLen - temp;
                    } else if (micByte[temp] == 0x00 && micByte[temp + 1] == 0x00 && micByte[temp + 2] == 0x00 && micByte[temp + 3] == 0x00) {
                        unDisposeLen = 0;
                    } else {
                        temp++;
                    }
                } else {
                    temp++;
                }
            }
            if (temp == unDisposeLen) {
                unDisposeLen = 0;
            }
        }
    }

    /**
     * 字节数组转字符串
     *
     * @param b          要转换的字节数组
     * @param charEncode 字符编码，如：UTF-8、GB2312，UTF-8编码一个汉字占三个字节，GB2312一个汉字占两个字节
     * @return 字符串
     */
    public static String byteToString(byte[] b, String charEncode) {
        String destObj = null;
        try {
            destObj = new String(b, charEncode);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return destObj.replaceAll("\0", " ");
    }


    /**
     * 接收串口数据接口
     */
    public interface IWakeUpListener {
        /**
         * 唤醒事件
         *
         * @param angle 角度
         */
        void onWakeUp(String angle);
    }

    /**
     * 接收五麦串口数据
     */
    private class MicReadThread extends Thread {
        @Override
        public void run() {
            super.run();

            while (!isInterrupted()) {
                try {
                    if (mMicInputStream != null) {
                        micResult();
                    }
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

}
